package com.binance.masterelection.service;

import java.util.Collections;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;

import com.binance.master.utils.IPUtils;
import com.google.common.collect.Lists;

import lombok.extern.log4j.Log4j2;

/**
 * master 选举模块，依赖微服务的discoveryclient
 */
@Log4j2
public class MasterElection {
    @Autowired
    private DiscoveryClient discoveryClient;
    @Value("${spring.application.name}")
    private String applcationName;

    public Boolean isMaster() {
        try {
            List<String> serviceNameList = discoveryClient.getServices();
            if (!serviceNameList.contains(applcationName)) {
                return false;
            }
            List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances(applcationName);
            if (CollectionUtils.isEmpty(serviceInstanceList)) {
                return false;
            }
            List<String> serviceIpList = Lists.newArrayList();
            for (ServiceInstance serviceInstance : serviceInstanceList) {
                serviceIpList.add(serviceInstance.getHost());
            }
            // 对iplist进行排序,这样做的目的是为了得到正确的顺序，
            // 我们无法保证eureka上的servicelist顺序是不变的
            // 排序下的至少逻辑上永远可以得出一个master
            Collections.sort(serviceIpList);
            String firstServiceIp = serviceIpList.get(0);
            String localIp = IPUtils.getIp();
            // 如果当前机器的ip处于iplist的第一个的话，那么它就是master
            Boolean isMaster = firstServiceIp.equals(localIp);
            log.info("MasterElection.isMaster: firstServiceIp={},localIp={},isMaster={}", firstServiceIp, localIp,
                    isMaster);
            return isMaster;
        } catch (Exception e) {
            log.error("MasterElection.isMaster Exception:", e);
            return false;
        }
    }
}
